/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ui.views;

import com.vaadin.data.Container;
import com.vaadin.data.Item;
import com.vaadin.data.util.BeanItemContainer;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.ComboBox;
import com.vaadin.ui.Component;
import com.vaadin.ui.ComponentContainer;
import com.vaadin.ui.DefaultFieldFactory;
import com.vaadin.ui.Field;
import com.vaadin.ui.Form;
import com.vaadin.ui.FormFieldFactory;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.Table;
import com.vaadin.ui.TableFieldFactory;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.TextField;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.Reindeer;
import entities.CvType;
import entities.JobType;
import entities.LanguageRecordType;
import entities.MscType;
import entities.ProjectType;
import entities.TitleType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import ui.controllers.FormController;

/**
 *
 * @author Spyros
 */
public class FormView {

    private Panel mainPanel;
    /*private ArrayList<java.lang.reflect.Field> fieldsArrayList;
    private Class[] dataClasses;*/
    private FormController controller;
    private TableFieldFactory defaultTableFieldFactory;

    public Component init(Integer userId) {
        controller = new FormController(userId);
        defaultTableFieldFactory = getDefaultTableFieldFactory();
        initilizeComponents();
        return mainPanel;
    }

    private void initilizeComponents() {
        mainPanel = new Panel();
        if (controller.isCommited()) {
            Label label = new Label("Η αίτηση έχει αποσταλεί");
            mainPanel.addComponent(label);
        } else if (controller.isOutOfDate()) {
            Label label = new Label("Η προθεσμία υποβολής αιτήσεων έχει λήξει.");
            mainPanel.addComponent(label);
        } else {

            ((VerticalLayout) mainPanel.getContent()).setSpacing(true);

            //areas of study
            final Form areasOfStudyForm = new Form();
            TextField area1 = new TextField("Ηλεκτρονική Μάθηση");
            TextField area2 = new TextField("Δικτυοκεντρικά Συστήματα");
            TextField area3 = new TextField("Ψηφιακά Δίκτυα και Επικοινωνίες");
            areasOfStudyForm.addField("area1", area1);
            areasOfStudyForm.addField("area2", area2);
            areasOfStudyForm.addField("area3", area3);
            areasOfStudyForm.setCaption("Κατεύθυνση που επιθυμείτε να ακολουθήσετε με σειρά προτίμησης");
            areasOfStudyForm.setWidth("750px");
            mainPanel.addComponent(areasOfStudyForm);

            //personal info
            final GridLayout gridLayout = new GridLayout(5, 4);
            gridLayout.setSpacing(true);
            final Form personalInfoForm = new Form(gridLayout) {

                @Override
                protected void attachField(Object propertyId, Field field) {
                    if (propertyId.equals("surname")) {
                        gridLayout.addComponent(field, 0, 0);
                    } else if (propertyId.equals("name")) {
                        gridLayout.addComponent(field, 1, 0);
                    } else if (propertyId.equals("dateofbirth")) {
                        gridLayout.addComponent(field, 2, 0);
                    } else if (propertyId.equals("placeofbirth")) {
                        gridLayout.addComponent(field, 3, 0);
                    } else if (propertyId.equals("idNo")) {
                        gridLayout.addComponent(field, 0, 1);
                    } else if (propertyId.equals("passportNo")) {
                        gridLayout.addComponent(field, 1, 1);
                    } else if (propertyId.equals("address")) {
                        gridLayout.addComponent(field, 0, 2, 1, 2);
                    } else if (propertyId.equals("address2")) {
                        gridLayout.addComponent(field, 2, 2, 3, 2);
                    } else if (propertyId.equals("homePhone")) {
                        gridLayout.addComponent(field, 0, 3);
                    } else if (propertyId.equals("mobPhone")) {
                        gridLayout.addComponent(field, 1, 3);
                    } else if (propertyId.equals("workPhone")) {
                        gridLayout.addComponent(field, 2, 3);
                    } else if (propertyId.equals("fax")) {
                        gridLayout.addComponent(field, 3, 3);
                    } else if (propertyId.equals("email")) {
                        gridLayout.addComponent(field, 4, 3);
                    }
                }
            };
            final FormFieldFactory oldFieldFactory = personalInfoForm.getFormFieldFactory();
            personalInfoForm.setFormFieldFactory(new FormFieldFactory() {

                @Override
                public Field createField(Item item, Object propertyId, Component uiContext) {
                    Field f = oldFieldFactory.createField(item, propertyId, uiContext);
                    if (propertyId.equals("surname")) {
                        f.setCaption("Επώνυμο");
                    } else if (propertyId.equals("name")) {
                        f.setCaption("Όνομα");
                    } else if (propertyId.equals("dateofbirth")) {
                        f.setCaption("Ημερομηνία");
                    } else if (propertyId.equals("placeofbirth")) {
                        f.setCaption("Τόπος γέννησης");
                    } else if (propertyId.equals("idNo")) {
                        f.setCaption("Αριθμός ταυτότητας");
                    } else if (propertyId.equals("passportNo")) {
                        f.setCaption("ή αριθμός διαβατηρίου");
                    } else if (propertyId.equals("address")) {
                        f.setCaption("Διεύθυνση κατοικίας");
                        f.setWidth("270px");
                    } else if (propertyId.equals("address2")) {
                        f.setCaption("Διεύθυνση επικοινωνίας");
                        f.setWidth("270px");
                    } else if (propertyId.equals("homePhone")) {
                        f.setCaption("Τηλέφωνο οικίας");
                    } else if (propertyId.equals("mobPhone")) {
                        f.setCaption("Κινητό");
                    } else if (propertyId.equals("workPhone")) {
                        f.setCaption("Τηλέφωνο εργασίας");
                    } else if (propertyId.equals("fax")) {
                        f.setCaption("fax");
                    } else if (propertyId.equals("email")) {
                        f.setCaption("E-mail");
                    }
                    if (f instanceof TextField) {
                        ((TextField) f).setNullRepresentation("");
                    }
                    return f;
                }
            });
            personalInfoForm.setVisibleItemProperties(new String[]{
                        "surname",
                        "name",
                        "dateofbirth",
                        "placeofbirth",
                        "idNo",
                        "passportNo",
                        "address",
                        "address2",
                        "homePhone",
                        "mobPhone",
                        "workPhone",
                        "fax",
                        "email"
                    });
            personalInfoForm.setItemDataSource(controller.getPersonalInfoDataSource());
            personalInfoForm.setCaption("Προσωπικά Στοιχεία");
            personalInfoForm.setWidth("750px");
            mainPanel.addComponent(personalInfoForm);

            //studies
            String[] studiesColumns = new String[]{
                "type",
                "level",
                "department",
                "datein",
                "dateout",
                "grade"
            };
            String[] studiesHeaders = new String[]{
                "ΑΕΙ ή ΤΕΙ",
                "Επίπεδο",
                "Τμήμα",
                "Ημερομηνία εισαγωγής",
                "Ημερομηνία αποφοίτησης",
                "Βαθμός πτυχίου"
            };
            TableFieldFactory studiesFieldFactory = new TableFieldFactory() {

                @Override
                public Field createField(Container container, Object itemId, Object propertyId, Component uiContext) {
                    Field f = defaultTableFieldFactory.createField(container, itemId, propertyId, uiContext);
                    if (propertyId.equals("type")) {
                        ComboBox comboBox = new ComboBox();
                        comboBox.addItem("Προπτυχιακές");
                        comboBox.addItem("Μεταπτυχιακές");
                        f = comboBox;
                    } else if (propertyId.equals("level")) {
                        ComboBox comboBox = new ComboBox();
                        comboBox.addItem("ΑΕΙ");
                        comboBox.addItem("ΤΕΙ");
                        f = comboBox;
                    }
                    return f;
                }
            };
            mainPanel.addComponent(getEditableTablePanel(controller.getStudiesBeanItemContainer(),
                    TitleType.class, studiesFieldFactory, studiesHeaders, studiesColumns, "Σπουδές"));

            //projects
            String[] projectsColumns = new String[]{
                "type",
                "title",
                "supervisor",
                "grade"
            };
            String[] projectsHeaders = new String[]{
                "Είδος Eργασίας",
                "Τίτλος",
                "Επιβλέπων Καθηγητής",
                "Βαθμός"
            };
            mainPanel.addComponent(getEditableTablePanel(controller.getProjectsBeanItemContainer(),
                    ProjectType.class, defaultTableFieldFactory, projectsHeaders, projectsColumns, "Πτυχιακές και Mεταπτυχιακές Διπλωματικές Εργασίες"));

            //awards
            String[] awardsColumns = new String[]{
                "award"
            };
            String[] awardsHeaders = new String[]{
                "Βραβεία, Διακρίσεις και Υποτροφίες"
            };
            mainPanel.addComponent(getEditableTablePanel(null, null, true, "award", defaultTableFieldFactory, awardsHeaders, awardsColumns, "Βραβεία, Διακρίσεις και Υποτροφίες"));

            //languages
            String[] languagesColumns = new String[]{
                "language",
                "level"
            };
            String[] languagesHeaders = new String[]{
                "Γλώσσα",
                "Δίπλωμα ή επίπεδο γνώσης"
            };
            mainPanel.addComponent(getEditableTablePanel(controller.getLanguagesBeanItemContainer(),
                    LanguageRecordType.class, defaultTableFieldFactory, languagesHeaders, languagesColumns, "Ξένες Γλώσσες"));

            //jobs
            String[] jobsColumns = new String[]{
                "position",
                "organization",
                "timeStart",
                "timeFinish"
            };
            String[] jobsHeaders = new String[]{
                "Θέση ευθύνης",
                "Οργανισμός",
                "Χρονικό διάστημα από",
                "Χρονικό διάστημα έως"
            };
            mainPanel.addComponent(getEditableTablePanel(controller.getJobsBeanItemContainer(),
                    JobType.class, defaultTableFieldFactory, jobsHeaders, jobsColumns, "Επαγγελματική Δραστηριότητα"));

            //research
            String[] researchColumns = new String[]{
                "research"
            };
            String[] researchHeaders = new String[]{
                "Ερευνητική Δραστηριότητα"
            };
            mainPanel.addComponent(getEditableTablePanel(null, null, true, "research",
                    defaultTableFieldFactory, researchHeaders, researchColumns, "Ερευνητική Δραστηριότητα"));

            //cv
            String[] cvsColumns = new String[]{
                "name",
                "title",
                "organization",
                "address",
                "phone",
                "email"
            };
            String[] cvsHeaders = new String[]{
                "Ονοματεπώνυμο",
                "Τίτλος",
                "Ίδρυμα/ Οργανισμός",
                "Διεύθυνση",
                "Τηλέφωνα",
                "Ε-mail"
            };
            mainPanel.addComponent(getEditableTablePanel(controller.getCvsBeanItemContainer(),
                    CvType.class, defaultTableFieldFactory, cvsHeaders, cvsColumns, "Συστατικές Επιστολές"));

            //msc
            String[] mscColumns = new String[]{
                "organization",
                "title"
            };
            String[] mscHeaders = new String[]{
                "Φορέας",
                "Τίτλος"
            };
            mainPanel.addComponent(getEditableTablePanel(controller.getMscBeanItemContainer(),
                    MscType.class, defaultTableFieldFactory, mscHeaders, mscColumns,
                    "Άλλα προγράμματα μεταπτυχιακών σπουδών (ΠΜΣ) στα οποία έχετε ή σκοπεύετε να κάνετε αίτηση"));

             //other info
            final TextArea otherInfo = new TextArea("Άλλες Πληροφορίες");
            otherInfo.setWidth("700px");
            mainPanel.addComponent(otherInfo);

            //save
            Button saveButton = new Button("Υποβολή");
            saveButton.addListener(new Button.ClickListener() {

                @Override
                public void buttonClick(ClickEvent event) {
                    areasOfStudyForm.commit();
                    controller.setAreasOfStudy(
                            areasOfStudyForm.getField("area1").getValue() == null ? "0" : areasOfStudyForm.getField("area1").getValue().toString(),
                            areasOfStudyForm.getField("area2").getValue() == null ? "0" : areasOfStudyForm.getField("area2").getValue().toString(),
                            areasOfStudyForm.getField("area3").getValue() == null ? "0" : areasOfStudyForm.getField("area3").getValue().toString());
                    personalInfoForm.commit();
                    controller.setPersonalInfo(personalInfoForm.getItemDataSource());
                    findTables(mainPanel);
                    otherInfo.commit();
                    controller.setOtherInfo(otherInfo.getValue().toString());
                    controller.save();
                }
            });
            mainPanel.addComponent(saveButton);
        }
    }

    private void findTables(ComponentContainer componentContainer) {
        for (Iterator it = componentContainer.getComponentIterator(); it.hasNext();) {
            Component component = (Component) it.next();
            if (component instanceof ComponentContainer) {
                findTables((ComponentContainer) component);
            } else if (component instanceof Table) {
                setTableValues((Table) component);
            }
        }
    }

    private void setTableValues(Table table) {
        if (table.getContainerDataSource() instanceof BeanItemContainer) {
            if (((BeanItemContainer) table.getContainerDataSource()).getBeanType().equals(TitleType.class)) {
                controller.setStudies((Collection<TitleType>) table.getItemIds());
            } else if (((BeanItemContainer) table.getContainerDataSource()).getBeanType().equals(ProjectType.class)) {
                controller.setProjects((Collection<ProjectType>) table.getItemIds());
            } else if (((BeanItemContainer) table.getContainerDataSource()).getBeanType().equals(LanguageRecordType.class)) {
                controller.setLanguages((Collection<LanguageRecordType>) table.getItemIds());
            } else if (((BeanItemContainer) table.getContainerDataSource()).getBeanType().equals(JobType.class)) {
                controller.setJobs((Collection<JobType>) table.getItemIds());
            } else if (((BeanItemContainer) table.getContainerDataSource()).getBeanType().equals(CvType.class)) {
                controller.setCvs((Collection<CvType>) table.getItemIds());
            } else if (((BeanItemContainer) table.getContainerDataSource()).getBeanType().equals(MscType.class)) {
                controller.setOtherMsc((Collection<MscType>) table.getItemIds());
            }
        } else {
            if (table.getContainerDataSource().getContainerPropertyIds().iterator().next().equals("award")) {
                ArrayList<String> awards = new ArrayList<String>();
                for (Iterator<? extends Object> it = table.getItemIds().iterator(); it.hasNext();) {
                    Integer id = (Integer) it.next();
                    awards.add(table.getItem(id).getItemProperty("award").getValue().toString());
                }
                controller.setAwards(awards);
            } else if (table.getContainerDataSource().getContainerPropertyIds().iterator().next().equals("research")) {
                ArrayList<String> research = new ArrayList<String>();
                for (Iterator<? extends Object> it = table.getItemIds().iterator(); it.hasNext();) {
                    Integer id = (Integer) it.next();
                    research.add(table.getItem(id).getItemProperty("research").getValue().toString());
                }
                controller.setResearch(research);
            }
        }
    }

    private TableFieldFactory getDefaultTableFieldFactory() {
        TableFieldFactory tableFieldFactory = new TableFieldFactory() {

            @Override
            public Field createField(Container container, Object itemId, Object propertyId, Component uiContext) {
                Field f = DefaultFieldFactory.get().createField(container, itemId, propertyId, uiContext);
                if (f instanceof TextField) {
                    ((TextField) f).setNullRepresentation("");
                }
                return f;
            }
        };
        return tableFieldFactory;
    }

    private Panel getEditableTablePanel(BeanItemContainer beanItemContainer, Class clazz,
            TableFieldFactory tableFieldFactory, String[] headers, String[] columns, String caption) {
        return getEditableTablePanel(beanItemContainer, clazz, false, null, tableFieldFactory, headers, columns, caption);
    }

    private Panel getEditableTablePanel(BeanItemContainer beanItemContainer, Class clazz,
            boolean listOfStrings, String property, TableFieldFactory tableFieldFactory,
            String[] headers, String[] columns, String caption) {
        Panel tablePanel = new Panel();
//        tablePanel.setStyleName(Reindeer.PANEL_LIGHT);
        Table table = new Table();
        if (tableFieldFactory != null) {
            table.setTableFieldFactory(tableFieldFactory);
        }
        table.setEditable(true);
        table.setSelectable(true);
        table.setPageLength(3);
        table.setWidth("800px");
        tablePanel.setCaption(caption);
        if (listOfStrings) {
            table.addContainerProperty(property, String.class, null);
        } else {
            table.setContainerDataSource(beanItemContainer);
        }
        if (headers != null) {
            table.setVisibleColumns(columns);
            table.setColumnHeaders(headers);
        }

        HorizontalLayout buttonsLayout = new HorizontalLayout();
        tablePanel.addComponent(table);
        tablePanel.addComponent(buttonsLayout);
        buttonsLayout.addComponent(getNewRecordButton(table, clazz));
        buttonsLayout.addComponent(getDeleteRecordButton(table));
        return tablePanel;

    }

    private Button getNewRecordButton(final Table table, final Class clazz) {
        Button button = new Button("+", new Button.ClickListener() {

            @Override
            public void buttonClick(ClickEvent event) {
                try {
                    if (clazz != null) {
                        table.addItem(clazz.newInstance());
                    } else {
                        table.addItem();
                    }
                } catch (InstantiationException ex) {
                    Logger.getLogger(FormView.class.getName()).log(Level.SEVERE, null, ex);
                } catch (IllegalAccessException ex) {
                    Logger.getLogger(FormView.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        return button;
    }

    private Button getDeleteRecordButton(final Table table) {
        Button button = new Button("-", new Button.ClickListener() {

            @Override
            public void buttonClick(ClickEvent event) {
                if (table.getValue() != null) {
                    table.removeItem(table.getValue());
                }
            }
        });
        return button;
    }

    /*
     * anything below is not used but remains for future use
     */
    // <editor-fold defaultstate="collapsed" desc="unused">
    /*
    private void initializeListOfFiels() {
    fieldsArrayList = new ArrayList<java.lang.reflect.Field>();
    dataClasses = new Class[]{String.class, Byte.class, BigDecimal.class, XMLGregorianCalendar.class};
    Class rootClass = DocumentType.class;
    getFields(rootClass);
    for (Iterator it = fieldsArrayList.iterator(); it.hasNext();) {
    java.lang.reflect.Field field = (java.lang.reflect.Field) it.next();
    mainPanel.addComponent(new Label(field.getName()));
    }
    }

    private void getFields(Class clazz) {
    java.lang.reflect.Field[] fields = clazz.getDeclaredFields();
    for (int i = 0; i < fields.length; i++) {
    java.lang.reflect.Field field = fields[i];
    //is field type data class
    boolean isDataClass = false;
    for (int j = 0; j < dataClasses.length; j++) {
    Class dataClass = dataClasses[j];
    if (field.getType().equals(dataClass)) {
    isDataClass = true;
    break;
    }
    }
    if (isDataClass) {
    System.out.println(field.getName() + " added");
    fieldsArrayList.add(field);
    } else if (field.getType().equals(List.class)) {
    System.out.println(field.getName() + " is a list");
    ParameterizedType pt = (ParameterizedType) field.getGenericType();
    getFields((Class) pt.getActualTypeArguments()[0]);
    } else {
    System.out.println(field.getName() + " not added");
    getFields(field.getType());
    }
    //            mainPanel.addComponent(new Label(field.getGenericType().toString()));
    }
    }*/
    // </editor-fold>
}
